/* eslint-disable */

class Watcher {
  key;
  global;
  fn;
  Dep;

  constructor(key, global, fn, Dep) {
    this.key = key;
    this.global = global;
    this.fn = fn;
    this.Dep = Dep;

    this.subscibeByGet();
  }

  //实例化Watcher的同时触发get，进行订阅
  subscibeByGet() {
    this.Dep.target = this;
    const arr = this.key.split(".");
    let val = this.global;
    arr.forEach((key) => {
      val = val[key];
    });
    this.Dep.target = undefined;
  }

  update() {
    const arr = this.key.split(".");
    let val = this.global;

    arr.forEach((key) => {
      val = val[key];
    });
    this.fn(val);
  }
}

class Dep {
  subs;

  constructor() {
    this.subs = [];
  }

  addSubs(watcher) {
    this.subs.push(watcher);
  }

  notify() {
    this.subs.forEach((item) => {
      item.update();
    });
  }
}

export default class Observer {
  Dep;
  Watcher;

  constructor() {
    this.Dep = Dep;
    this.Watcher = Watcher;
  }

  Observe(data) {
    const _this = this;
    for (const key in data) {
      let val = data[key];
      this.observe(data[key]);
      const dep = new Dep();
      Object.defineProperty(data, key, {
        configurable: true,
        get() {
          _this.Dep.target && dep.addSubs(_this.Dep.target);
          return val;
        },
        set(newValue) {
          if (val === newValue) {
            return;
          }
          val = newValue;
          _this.observe(newValue);
          dep.notify();
        },
      });
    }
  }

  observe(data) {
    if (!data || typeof data !== "object") return;
    this.Observe(data);
  }

  makeWatcher(key, global, fn) {
    new this.Watcher(key, global, fn, this.Dep);
  }
}